package com.yckj.ytracker.api.factory;

import com.yckj.ytracker.api.enums.TrackerType;
import com.yckj.ytracker.api.exception.YTrackerException;
import com.yckj.ytracker.api.trace.ITracerClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author liuwei
 * @version 2017/10/14 下午2:08
 * @description tracker对象获取工厂类
 * @see
 * @since 1.0
 */
public class TrackerFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(TrackerFactory.class);

    private static volatile InitStatus INIT_STATUS = InitStatus.UNINIT;

    public static ITracerClient getTracker(TrackerType trackerType) {
        ITrackerFactory trackerFactory = getTrackerFactory();
        return trackerFactory.getTracker(trackerType);
    }

    private static ITrackerFactory getTrackerFactory() {
        if (INIT_STATUS == InitStatus.UNINIT) {
            synchronized (TrackerFactory.class) {
                INIT_STATUS = InitStatus.INITIALIZING;
                init();
            }
        }
        switch (INIT_STATUS) {
            case UNINIT:
            case INITIALIZING:
                throw new YTrackerException("YTracker:init error!");
            case FAIL:
                throw new YTrackerException("YTracker:TrackerFactory can't init!");
            case SUCCESS:
                return DefaultTrackerFactory.getInstance();
        }
        return null;
    }

    private static void init() {
        try {
            DefaultTrackerFactory.getInstance();
            INIT_STATUS = InitStatus.SUCCESS;
            LOGGER.debug("YTracker:Success to load class DefaultTrackerFactory.");
        } catch (NoClassDefFoundError noClassDefFoundError) {
            String msg = noClassDefFoundError.getMessage();
            if (msg != null && msg.contains("DefaultTrackerFactory")) {
                LOGGER.error("YTracker: cannot find DefaultTrackerFactory!");
            }
            bindFailed();
        } catch (NoSuchMethodError noSuchMethodError) {
            String msg = noSuchMethodError.getMessage();
            if (msg != null && msg.contains("DefaultTrackerFactory.getInstance()")) {
                LOGGER.error("YTracker: cannot find DefaultTrackerFactory.getInstance()!");
            }
            bindFailed();
        } catch (Throwable t) {
            LOGGER.error("YTracker: unexpected initialization failure:{}", t);
            bindFailed();
        }

    }

    private static void bindFailed() {
        INIT_STATUS = InitStatus.FAIL;
        throw new YTrackerException("YTracker:failed to instantiate TrackerFactory!");
    }

    /**
     * @author liuwei
     * @version 2017/10/14 下午2:12
     * @description 初始状态枚举 0:未初始化,1:正在初始化,2:失败,3:成功
     * @see
     * @since 1.0
     */
    private enum InitStatus {
        UNINIT(0), INITIALIZING(1), FAIL(2), SUCCESS(3);
        private int key;

        private InitStatus(int key) {
            this.key = key;
        }

        public int getKey() {
            return key;
        }
    }
}
